/*
 * BSM6.0
 *
 * Copyright 2012-2013 (C) SINODATA CO., LTD. All Rights Reserved.
 */
package com.sinodata.bsm.center.web.action.event;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.springframework.beans.factory.annotation.Autowired;

import com.sinodata.bsm.center.bean.Condition;
import com.sinodata.bsm.center.bean.EventRuleBean;
import com.sinodata.bsm.center.bean.Page;
import com.sinodata.bsm.center.bean.ResTypeBean;
import com.sinodata.bsm.center.cache.AttributeCache;
import com.sinodata.bsm.center.cache.DefaultEventExcludeRuleCache;
import com.sinodata.bsm.center.cache.DefaultEventRuleCache;
import com.sinodata.bsm.center.cache.EventRuleCache;
import com.sinodata.bsm.center.cache.EventTypeCache;
import com.sinodata.bsm.center.cache.PropertyCache;
import com.sinodata.bsm.center.cache.ResCache;
import com.sinodata.bsm.center.cache.ResTypeCache;
import com.sinodata.bsm.center.expression.Expressions;
import com.sinodata.bsm.center.service.event.EventRuleService;
import com.sinodata.bsm.center.util.web.Struts2Utils;
import com.sinodata.bsm.center.web.action.BaseAction;
import com.sinodata.bsm.common.constants.EventConstants;
import com.sinodata.bsm.common.utils.StringUtil;
import com.sinodata.bsm.common.vo.Attribute;
import com.sinodata.bsm.common.vo.DefaultEventExcludeRule;
import com.sinodata.bsm.common.vo.DefaultEventRule;
import com.sinodata.bsm.common.vo.EventRule;
import com.sinodata.bsm.common.vo.Property;

/**
 * <p>
 * Description: 
 * </p>
 *
 * @author dongyushi
 * @version 1.0

 * <p>
 * History: 
 *
 * Date                     Author         Version     Description
 * ---------------------------------------------------------------------------------
 * 2012-11-26 上午10:42:08          dongyushi        1.0         To create
 * </p>
 *
 * @since 
 * @see     
 */
public class DefaultEventRuleAction extends BaseAction<DefaultEventRule> {

    private static final long serialVersionUID = 6998299192393583314L;
    @Autowired
    private EventRuleService eventRuleService;
    @Autowired
    private EventTypeCache eventTypeCache;
    @Autowired
    private ResTypeCache resTypeCache;
    @Autowired
    private ResCache resCache;
    @Autowired
    private PropertyCache propertyCache;
    @Autowired
    private AttributeCache attributeCache;
    @Autowired
    private EventRuleCache eventRuleCache;
    @Autowired
    private DefaultEventRuleCache defaultEventRuleCache;
    @Autowired
    private DefaultEventExcludeRuleCache defaultEventExcludeRuleCache;

    private DefaultEventRule entity;

    private Long id;

    /**
     * 跳转至默认表格页面
     * 
     * @return
     */
    public String common() {
        return "common";
    }

    @Override
    public DefaultEventRule getModel() {
        return entity;
    }

    @Override
    public String list() throws Exception {
        String eventTypeName = request.getParameter("eventTypeName");
        String resTypeName = request.getParameter("resTypeName");
        Condition condition = new Condition();
        Map<String, String> where = new HashMap<String, String>();
        if (eventTypeName != null && !eventTypeName.equals("")) {
            where.put("eventTypeName", eventTypeName.toLowerCase());
        }
        if (resTypeName != null && !resTypeName.equals("")) {
            where.put("resTypeName", resTypeName.toLowerCase());
        }
        condition.setWhere(where);
        Map<String, String> orderMap = new HashMap<String, String>();
        String order = request.getParameter("sSortDir_0");
        String col = request.getParameter("mDataProp_" + request.getParameter("iSortCol_0"));
        if (!col.equals("op")) {
            orderMap.put(col, order);
        }
        Page<DefaultEventRule> page = new Page<DefaultEventRule>();
        page.setOrder(orderMap);
        page.setPageNo(Integer.valueOf(request.getParameter("iDisplayStart")) / Integer.valueOf(request.getParameter("iDisplayLength")) + 1);
        page.setPageSize(Integer.valueOf(request.getParameter("iDisplayLength")));
        Page<DefaultEventRule> aaData = eventRuleService.findDefaultEventRuleByPage(page, condition);

        JSONObject json = new JSONObject();
        json.element("iTotalRecords", page.getTotal());
        json.element("iTotalDisplayRecords", page.getTotal());
        JSONArray array = new JSONArray();
        for (DefaultEventRule defaultEventRule : aaData.getRows()) {
            JSONObject obj = new JSONObject();
            obj.element("op", "<div style='width: 60px'>&nbsp;&nbsp;<a href='javascript:edit(" + defaultEventRule.getId() + ");'><img src='../style/default/bsm/images/edit.gif' title='修改'></a>&nbsp;<a href='javascript:" + (defaultEventRule.getStatus() == 0 ? "start" : "stop") + "(" + defaultEventRule.getId() + ");'><img src='../style/default/bsm/images/" + (defaultEventRule.getStatus() == 0 ? "start.gif' title='全局启用'" : "stop.gif' title='全局禁用'") + "></a><div>");
            obj.element("resTypeName", resTypeCache.get(defaultEventRule.getResTypeId()).getName());
            obj.element("eventTypeName", eventTypeCache.get(defaultEventRule.getEventTypeId()).getName());
            obj.element("levelName", "<img src='../style/default/images/" + defaultEventRule.getLevel() + ".gif' title='" + EventConstants.getLevelDesc(defaultEventRule.getLevel()) + "' />" + EventConstants.getLevelDesc(defaultEventRule.getLevel()));
            obj.element("expr", exrpFormate(defaultEventRule.getExpr()));
            obj.element("status", defaultEventRule.getStatus() == 1 ? "全局启用" : "全局禁用");
            obj.element("statusIndex", defaultEventRule.getStatus() == 1 ? "1" : "0");
            obj.element("id", defaultEventRule.getId());
            array.add(obj);
        }
        json.element("aaData", array);
        renderText(json.toString());
        return null;

    }

    private String editFormate(String str) {
        List<String> nodes1 = Expressions.parseNodes(Pattern.compile("(attr\\(\\$resid,\\d+[L|l]?\\))"), str);
        for (int i = 0; i < nodes1.size(); i++) {
            String node = nodes1.get(i);
            String attrId = node.split(",")[1].substring(0, node.split(",")[1].length() - 2);
            Attribute a = attributeCache.get(Long.valueOf(attrId));
            String m = "$A{" + node.split(",")[0].substring(node.split(",")[0].lastIndexOf("(") + 1, node.split(",")[0].length()) + ":" + a.getName() + "}";
            str = StringUtil.replace(str, node, m);
        }
        List<String> nodes2 = Expressions.parseNodes(Pattern.compile("(prop\\(\\$resid,\\d+[L|l]?\\))"), str);
        for (int i = 0; i < nodes2.size(); i++) {
            String node = nodes2.get(i);
            //解析prop
            String propId = node.split(",")[1].substring(0, node.split(",")[1].length() - 2);
            Property p = propertyCache.get(Long.valueOf(propId));
            String m = "$P{" + node.split(",")[0].substring(node.split(",")[0].lastIndexOf("(") + 1, node.split(",")[0].length()) + ":" + p.getName() + "}";
            str = StringUtil.replace(str, node, m);
        }
        List<String> nodes3 = Expressions.parseNodes(Pattern.compile("(tprop\\(\\$resid,\\d+[L|l]?,\\S+\\))"), str);
        for (int i = 0; i < nodes3.size(); i++) {
            String node = nodes3.get(i);
            //解析prop
            String propId = node.split(",")[1].substring(0, node.split(",")[1].length() - 1);
            Property p = propertyCache.get(Long.valueOf(propId));
            String m = "$TP{" + node.split(",")[0].substring(node.split(",")[0].lastIndexOf("(") + 1, node.split(",")[0].length()) + ":" + p.getName() + ":" + node.split(",")[2].substring(0, node.split(",")[2].length() - 1) + "}";
            str = StringUtil.replace(str, node, m);
        }
        return str;
    }

    private String exrpFormate(String expr) {
        while (expr.indexOf(".equals(") != -1) {
            expr = replaceEquals(expr);
        }
        List<String> nodes1 = Expressions.parseNodes(Pattern.compile("(attr\\(\\$resid,\\d+[L|l]?\\))"), expr);
        for (int i = 0; i < nodes1.size(); i++) {
            String node = nodes1.get(i);
            String m = explainAttrParameter(node);
            expr = StringUtil.replace(expr, node, m);
        }
        List<String> nodes2 = Expressions.parseNodes(Pattern.compile("(prop\\(\\$resid,\\d+[L|l]?\\))"), expr);
        for (int i = 0; i < nodes2.size(); i++) {
            String node = nodes2.get(i);
            String m = explainPropParameter(node);
            expr = StringUtil.replace(expr, node, m);
        }
        List<String> nodes3 = Expressions.parseNodes(Pattern.compile("(inc\\(\\$resid,\\d+[L|l]?,\\d+\\))"), expr);
        for (int i = 0; i < nodes3.size(); i++) {
            String node = nodes3.get(i);
            String m = explainIncParameter(node);
            expr = StringUtil.replace(expr, node, m);
        }
        List<String> nodes4 = Expressions.parseNodes(Pattern.compile("(lastPropValue\\(\\$resid,\\d+[L|l]?\\))"), expr);
        for (int i = 0; i < nodes4.size(); i++) {
            String node = nodes4.get(i);
            String m = explainLastPropParameter(node);
            expr = StringUtil.replace(expr, node, m);
        }
        List<String> nodes5 = Expressions.parseNodes(Pattern.compile("(tprop\\(\\$resid,\\d+[L|l]?,\\S+\\))"), expr);
        for (int i = 0; i < nodes5.size(); i++) {
            String node = nodes5.get(i);
            String m = explainTPropParameter(node);
            expr = StringUtil.replace(expr, node, m);
        }
        return expr;
    }

    //inc转换成name
    private String explainIncParameter(String temp) {
        StringBuffer sbuffer = new StringBuffer();
        String[] a = StringUtil.convertStringToStringArray(temp, ",");
        Long propId = Long.valueOf(a[1].substring(0, a[1].lastIndexOf("L")));
        Property property = propertyCache.get(propId);
        sbuffer.append(property.getName());
        int second = Integer.parseInt(a[2].substring(0, a[2].indexOf(")")));
        int minute = 0;
        //下面词条去掉request 因为这一部分要与指标一块使用 而指标是与部属环境相关的
        if (second % 60 == 0) {
            minute = second / 60;
            sbuffer.append(minute + "分钟");
        } else {
            minute = second / 60;
            second = second - minute * 60;
            if (minute > 0) {
                sbuffer.append(minute + "分钟" + second + "秒");
            } else {
                sbuffer.append(second + "秒");
            }
        }
        return sbuffer.toString();
    }

    //attr转换name
    private String explainAttrParameter(String temp) {
        String attrId = temp.substring(temp.indexOf(",") + 1, temp.length() - 2);
        Attribute attribute = attributeCache.get(Long.valueOf(attrId));
        String unit = (attribute.getDataUnit() == null || attribute.getDataUnit().equals("")) ? "" : "(" + attribute.getDataUnit() + ")";
        return attribute.getName() + unit;
    }

    //prop转换name
    private String explainPropParameter(String temp) {
        StringBuffer sb = new StringBuffer();
        String propId = temp.substring(temp.indexOf(",") + 1, temp.length() - 2);
        Property property = propertyCache.get(Long.parseLong(propId));
        sb.append(property.getName());
        String unit = (property.getDataUnit() == null || property.getDataUnit().equals("")) ? "" : "(" + property.getDataUnit() + ")";
        sb.append(unit);
        return sb.toString();
    }

    //tprop转换name
    private String explainTPropParameter(String temp) {
        StringBuffer sb = new StringBuffer();
        String propId = temp.substring(temp.indexOf(",") + 1, temp.lastIndexOf(",") - 1);
        Property property = propertyCache.get(Long.parseLong(propId));
        sb.append(property.getName() + ":" + temp.substring(temp.lastIndexOf(",") + 1, temp.length() - 1));
        String unit = (property.getDataUnit() == null || property.getDataUnit().equals("")) ? "" : "(" + property.getDataUnit() + ")";
        sb.append(unit);
        return sb.toString();
    }

    //Lastprop转换name
    private String explainLastPropParameter(String temp) {
        StringBuffer sb = new StringBuffer();
        String propId = temp.substring(temp.indexOf(",") + 1, temp.length() - 2);
        Property property = propertyCache.get(Long.parseLong(propId));
        sb.append("上次" + property.getName());
        String unit = (property.getDataUnit() == null || property.getDataUnit().equals("")) ? "" : "(" + property.getDataUnit() + ")";
        sb.append(unit);
        return sb.toString();
    }

    //转换.equals
    private static String replaceEquals(String str) {
        int index = str.indexOf(".equals(");
        if (index == -1) {
            return str;
        }
        String str1 = str.substring(0, index);
        String str2 = str.substring(index + 8);
        index = -1;
        int s = 0;
        for (int i = 0; i < str2.length(); i++) {
            char ch = str2.charAt(i);
            if (ch == '(') {
                s++;
            } else if (ch == ')') {
                if (s > 0) {
                    s--;
                } else {
                    index = i;
                    break;
                }
            }
        }
        if (index == -1) {
            // 异常
        }
        String str3 = str2.substring(0, index);

        String str4 = "";
        if (str2.length() > index) {
            str4 = str2.substring(index + 1);
        }
        return str1 + "==" + str3 + str4;
    }

    public String stop() {
        Long id = Long.valueOf(request.getParameter("id"));
        DefaultEventRule defaultEventRule = defaultEventRuleCache.get(id);
        //停用默认规则
        defaultEventRule.setStatus(0);
        eventRuleService.updateDefaultEventRule(defaultEventRule);
        defaultEventRuleCache.put(defaultEventRule.getId(), defaultEventRule);
        EventRuleBean.stopDefaultEventRule(defaultEventRule);
        return null;
    }

    public String start() {
        Long id = Long.valueOf(request.getParameter("id"));
        DefaultEventRule defaultEventRule = defaultEventRuleCache.get(id);
        //启用默认规则
        defaultEventRule.setStatus(1);
        eventRuleService.updateDefaultEventRule(defaultEventRule);
        //某个资源下有自定义的规则，则禁用此条默认规则  加入到禁用默认规则表中
        for (EventRule eventRule : eventRuleCache.getEventRuleByEventTypeId(defaultEventRule.getEventTypeId())) {
            if (eventRule.getLevel().equals(defaultEventRule.getLevel()) && eventRule.getStatus().equals(1)) {
                DefaultEventExcludeRule defaultEventExcludeRule = defaultEventExcludeRuleCache.getByResIdDefaultEventRuleId(eventRule.getResId(), defaultEventRule.getId());
                if (defaultEventExcludeRule == null) {
                    DefaultEventExcludeRule defaultEventExcludeRule1 = new DefaultEventExcludeRule();
                    defaultEventExcludeRule1.setResId(eventRule.getResId());
                    defaultEventExcludeRule1.setDefaultEventRuleId(id);
                    eventRuleService.addDefaultEventExcludeRule(defaultEventExcludeRule1);
                    defaultEventExcludeRuleCache.put(defaultEventExcludeRule1.getId(), defaultEventExcludeRule1);
                    EventRuleBean.stopDefaultEventRule(defaultEventRule, eventRule.getResId());
                }
            }
        }
        defaultEventRuleCache.put(defaultEventRule.getId(), defaultEventRule);
        EventRuleBean.startDefaultEventRule(defaultEventRule);
        return null;
    }

    @Override
    public String input() throws Exception {
        Long id = Long.valueOf(request.getParameter("id"));
        DefaultEventRule defaultEventRule = defaultEventRuleCache.get(id);
        Struts2Utils.getRequest().setAttribute("defaultEventRule", defaultEventRule);
        Struts2Utils.getRequest().setAttribute("eventTypeName", eventTypeCache.get(defaultEventRule.getEventTypeId()).getName());
        Struts2Utils.getRequest().setAttribute("resTypeName", resTypeCache.get(defaultEventRule.getResTypeId()).getName());
        Struts2Utils.getRequest().setAttribute("expr", editFormate(defaultEventRule.getExpr()));
        Struts2Utils.getRequest().setAttribute("msg", editFormate(defaultEventRule.getMsg()));
        return "update";
    }

    public String editExprMsg() throws Exception {
        String flag = request.getParameter("flag");
        DefaultEventRule defaultEventRule = defaultEventRuleCache.get(id);
        if (flag.equals("msg")) {
            String msg = new String(request.getParameter("msg").getBytes("ISO-8859-1"), "UTF-8");
            msg = msg.replace(" ", "----");
            msg = java.net.URLDecoder.decode(msg, "UTF-8");
            msg = msg.replace("----", "+");
            Struts2Utils.getRequest().setAttribute("exprOrMsg", msg);
        } else if (flag.equals("expr")) {
            String expr = new String(request.getParameter("expr").getBytes("ISO-8859-1"), "UTF-8");
            expr = expr.replace(" ", "----");
            expr = java.net.URLDecoder.decode(expr, "UTF-8");
            expr = expr.replace("----", "+");
            Struts2Utils.getRequest().setAttribute("exprOrMsg", expr);
        }
        Struts2Utils.getRequest().setAttribute("flag", flag);
        Struts2Utils.getRequest().setAttribute("resTypeId", defaultEventRule.getResTypeId());
        return "addExprMsg";
    }

    //指标下拉框
    public String propertyList() {
        ResTypeBean resTypeBean = ResTypeBean.get(Long.valueOf(request.getParameter("resTypeId")));
        List<Property> listProperty = resTypeBean.properties();
        List<Map<String, String>> listResult = new ArrayList<Map<String, String>>();
        if (listProperty != null) {
            Map<String, String> map1 = new HashMap<String, String>();
            map1.put("id", "");
            map1.put("name", "选择指标");
            listResult.add(map1);
            for (Property property : listProperty) {
                if (property.getDataTypeId() == 4) {
                    for (String colName : property.getFormat().split("[|]")) {
                        Map<String, String> map = new HashMap<String, String>();
                        map.put("id", "$TP{$resid:" + property.getName() + ":" + colName + "}");
                        map.put("name", property.getName() + ":" + colName);
                        listResult.add(map);
                    }
                } else {
                    Map<String, String> map = new HashMap<String, String>();
                    map.put("id", "$P{$resid:" + property.getName() + "}");
                    String name = property.getName();
                    if (property.getDataUnit() != null) {
                        name = name + "(" + property.getDataUnit() + ")";
                    }
                    map.put("name", name);
                    listResult.add(map);
                }
            }
        }
        Struts2Utils.renderJson(listResult);
        return null;
    }

    //属性下拉框
    public String attributeList() {
        ResTypeBean resTypeBean = ResTypeBean.get(Long.valueOf(request.getParameter("resTypeId")));
        List<Attribute> listAttribute = resTypeBean.attributes();
        List<Map<String, String>> listResult = new ArrayList<Map<String, String>>();
        if (listAttribute != null) {
            Map<String, String> map1 = new HashMap<String, String>();
            map1.put("id", "");
            map1.put("name", "选择属性");
            listResult.add(map1);
            for (Attribute attribute : listAttribute) {
                Map<String, String> map = new HashMap<String, String>();
                map.put("id", "$A{$resid:" + attribute.getName() + "}");
                String name = attribute.getName();
                map.put("name", name);
                listResult.add(map);
            }
        }
        Struts2Utils.renderJson(listResult);
        return null;
    }

    public String formateExprOrMsg(String exprOrMsg, Long resTypeId) {
        //解析prop
        Pattern compilePattern = Pattern.compile("(\\$P\\{(\\$resid):([^\\}]+)\\})");
        Matcher matcher = compilePattern.matcher(exprOrMsg);
        while (matcher.find()) {
            String str = matcher.group(1);
            String propName = matcher.group(3).trim();
            Long propId = -1l;
            ResTypeBean resTypeBean = ResTypeBean.get(resTypeId);
            List<Property> listProperty = resTypeBean.properties();
            for (Property p : listProperty) {
                if (p.getName().equals(propName)) {
                    propId = p.getId();
                    break;
                }
            }
            String newStr = "prop($resid," + propId + "L)";
            exprOrMsg = exprOrMsg.replace(str, newStr);
        }
        //解析attr
        Pattern compilePattern1 = Pattern.compile("(\\$A\\{(\\$resid):([^\\}]+)\\})");
        Matcher matcher1 = compilePattern1.matcher(exprOrMsg);
        while (matcher1.find()) {
            String str = matcher1.group(1);
            String attrName = matcher1.group(3).trim();
            Long attrId = -1l;
            ResTypeBean resTypeBean1 = ResTypeBean.get(resTypeId);
            List<Attribute> listAttribute = resTypeBean1.attributes();
            for (Attribute a : listAttribute) {
                if (a.getName().equals(attrName)) {
                    attrId = a.getId();
                }
            }
            String newStr = "attr($resid," + attrId + "L)";
            exprOrMsg = exprOrMsg.replace(str, newStr);
        }
        //解析tprop
        Pattern compilePattern4 = Pattern.compile("(\\$TP\\{(\\$resid):([^\\}]+):([^\\}]+)\\})");
        Matcher matcher4 = compilePattern4.matcher(exprOrMsg);
        while (matcher4.find()) {
            String str = matcher4.group(1);
            String propName = matcher4.group(3).trim();
            String colName = matcher4.group(4).trim();
            Long propId = -1l;
            ResTypeBean resTypeBean = ResTypeBean.get(resTypeId);
            List<Property> listProperty = resTypeBean.properties();
            for (Property p : listProperty) {
                if (p.getName().equals(propName)) {
                    propId = p.getId();
                    break;
                }
            }
            String newStr = "tprop($resid," + propId + "L," + colName + ")";
            exprOrMsg = exprOrMsg.replace(str, newStr);
        }
        return exprOrMsg;
    }

    public String validateExpress() throws Exception {
        String express = new String(request.getParameter("express").getBytes("ISO-8859-1"), "UTF-8");
        express = express.replace(" ", "----");
        express = java.net.URLDecoder.decode(express, "UTF-8");
        express = express.replace("----", "+");
        express = formateExprOrMsg(express, Long.valueOf(request.getParameter("resTypeId")));
        String resId = resCache.findAll() == null ? "-1" : String.valueOf(resCache.findAll().get(0).getId());
        express = StringUtil.replace(express, "$resid", resId);
        try {
            if (!express.contains("tprop")) {
                Expressions.test(express);
            }
        } catch (Exception ex) {
            logger.error("Failed to validateExpress,express=" + express, ex);
            renderText("false");
            return null;
        }
        renderText("true");
        return null;
    }

    public String viewMsg() throws Exception {
        String msg = new String(request.getParameter("msg").getBytes("ISO-8859-1"), "UTF-8");
        msg = msg.replace(" ", "----");
        msg = java.net.URLDecoder.decode(msg, "UTF-8");
        msg = msg.replace("----", "+");
        msg = formateExprOrMsg(msg, Long.valueOf(request.getParameter("resTypeId")));
        String resId = resCache.findAll() == null ? "-1" : String.valueOf(resCache.findAll().get(0).getId());
        msg = StringUtil.replace(msg, "$resid", resId);
        try {
            if (!msg.contains("tprop")) {
                Object o = Expressions.test(msg);
                msg = o.toString();
            }
        } catch (Exception e) {
            Struts2Utils.getRequest().setAttribute("msg", "预览消息失败,请确认消息设置是否正确");
            return "viewmsg";
        }
        msg = msg.replace(" ", "&nbsp; ");
        Struts2Utils.getRequest().setAttribute("msg", msg);
        return "viewmsg";
    }

    @Override
    public String save() throws Exception {
        entity.setExpr(formateExprOrMsg(entity.getExpr(), entity.getResTypeId()));
        entity.setMsg(formateExprOrMsg(entity.getMsg(), entity.getResTypeId()));
        eventRuleService.updateDefaultEventRule(entity);
        defaultEventRuleCache.put(entity.getId(), entity);
        EventRuleBean.startDefaultEventRule(entity);
        return null;
    }

    @Override
    public String delete() throws Exception {
        return null;
    }

    @Override
    protected void prepareModel() throws Exception {
        if (id != null) {
            entity = defaultEventRuleCache.get(id);
            if (entity == null) {
                entity = new DefaultEventRule();
            }
        } else {
            entity = new DefaultEventRule();
        }
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

}
